package com.wzh.org.graphics

import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.graphics.*
import android.util.DisplayMetrics
import android.util.Log
import android.view.MotionEvent
import android.view.View

class OrgTreeView(context: Context, data: OrgTreeNode) : View(context) {

    private val mMetrics = DisplayMetrics();

    /**
     * 顶部标题高度
     */
    private var topTitleHeight = 0.0f

    /**
     * 单元格宽度
     */
    private var gridWidth: Float = 0.0f

    /**
     * 单元格高度
     */
    private var gridHeight = 0.0f

    /**
     * 节点宽度
     */
    private var nodeWidth = 0.0f

    /**
     * 节点高度
     */
    private var nodeHeight = 0.0f

    /**
     * 整体图距离顶部的距离
     */
    private var wholeMarginTop = 0.0f

    /**
     * 整体图距离左边的距离
     */
    private var wholeMarginLeft = 0.0f

    /**
     * 垂直方向连接线的高度
     */
    private var nodeMarginVertical = 0.0f

    /**
     * 姓名marginLeft
     */
    private var nameMarginLeft = 0.0f

    /**
     * 姓名marginTop
     */
    private var nameMarginTop = 0.0f

    /**
     * 角色名称marginLeft
     */
    private var roleNameMarginLeft = 0.0f

    private var roleBottomLineWidth = 0.0f

    /**
     * 角色名称marginTop
     */
    private var roleNameMarginTop = 0.0f

    private var nodeData: OrgTreeNode

    private var selectedNode: OrgTreeNode? = null

    private var dropingNode: OrgTreeNode? = null


    private var paintBg = Paint().apply {
        color = Color.parseColor("#B9E8FE")
    }

    private val paintRectF = Paint().apply {
        color = Color.WHITE
        style = Paint.Style.FILL
    }

    private val paintRectFStroke = Paint().apply {
        color = Color.parseColor("#5E77C7")
        style = Paint.Style.STROKE
        strokeWidth = 2f
    }

    private val paintName: Paint? = Paint().apply {
        color = Color.BLACK
        strokeWidth = 1f
    }
    private val paintRoleName: Paint? = Paint().apply {
        color = Color.GRAY
        strokeWidth = 1f
    }
    private val paintLine: Paint? = Paint().apply {
        color = Color.parseColor("#5E77C7")
        strokeWidth = 2f
    }

    private val paintText: Paint? = Paint().apply {
        color = Color.WHITE
        strokeWidth = 1f
    }

    private val paintDashLine:Paint = Paint().apply {
        color = Color.GRAY
        strokeWidth = 1f
        pathEffect = DashPathEffect(floatArrayOf(10f,5f),0f)
    }

    private val paintAddBtn:Paint = Paint().apply {
        color = Color.BLUE
        strokeWidth = 1f
    }

    private var rectF: RectF = RectF()

    var clickX = 0.0f
    var clickY = 0.0f
    var lastX = 0.0f
    var lastY = 0.0f
    var lastScreenOffsetX = 0.0f
    var lastScreenOffsetY = 0.0f
    var screenOffsetX = 0.0f
    var screenOffsetY = 0.0f

    /**
     * 屏幕状态(0:未点击,1:单手,否则多手指)
     */
    private var mMode = 0
    private var canMovingScreen = false
    private var zoomPercent = 1.0f
    private var prevZoomPercent = 1.0f

    var delRectHeight = 0.0f
    var triggerDel = false

    var saveRectHeight = 0.0f
    var needSave = false

    init {
        (context as Activity).windowManager.defaultDisplay.getMetrics(this.mMetrics)
        this.nodeData = data
        initPx()
    }


    private fun initPx() {
        this.topTitleHeight = this.dp2px(32f).toFloat()
        this.gridWidth = this.dp2px(120f).toFloat() * prevZoomPercent * zoomPercent
        this.gridHeight = this.dp2px(90f).toFloat() * prevZoomPercent * zoomPercent
        this.nodeWidth = this.dp2px(96f).toFloat() * prevZoomPercent * zoomPercent
        this.nodeHeight = this.dp2px(76f).toFloat() * prevZoomPercent * zoomPercent
        this.wholeMarginTop = this.dp2px(50f).toFloat() * prevZoomPercent * zoomPercent
        this.nodeMarginVertical = this.dp2px(20f).toFloat() * prevZoomPercent * zoomPercent
        this.nameMarginLeft = this.dp2px(30f).toFloat() * prevZoomPercent * zoomPercent
        this.nameMarginTop = this.dp2px(26f).toFloat() * prevZoomPercent * zoomPercent
        this.roleNameMarginLeft = this.dp2px(30f).toFloat() * prevZoomPercent * zoomPercent
        this.roleNameMarginTop = this.dp2px(44f).toFloat() * prevZoomPercent * zoomPercent
        this.roleBottomLineWidth = this.dp2px(76f).toFloat() * prevZoomPercent * zoomPercent
        this.paintName?.textSize =
            this.sp2px(context, 16f).toFloat() * prevZoomPercent * zoomPercent
        this.paintRoleName?.textSize =
            this.sp2px(context, 12f).toFloat() * prevZoomPercent * zoomPercent
        this.paintAddBtn?.textSize =
            this.sp2px(context, 12f).toFloat() * prevZoomPercent * zoomPercent
        this.paintText?.textSize = this.sp2px(context, 14f).toFloat()
        this.delRectHeight = this.dp2px(50f).toFloat()
        this.saveRectHeight = this.dp2px(40f).toFloat()

    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        drawView(canvas!!)
    }

    private fun drawView(canvas: Canvas) {

        //先计算
        calcAll()
        //画出背景图
        paintBg.color = Color.parseColor("#B9E8FE")
        canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paintBg)

        //画出节点和连接线
        drawRectAll(canvas, nodeData, false)
        drawTopTitle(canvas);
        //画出移动的节点和连接线
        if (selectedNode != null && selectedNode!!.isMoving == true) {
            canvas.saveLayerAlpha(0f, 0f, width.toFloat(), height.toFloat(), 70)
            paintBg.color = Color.parseColor("#333333")
            canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paintBg)
            canvas.restore()

            drawFloatTopTitle(canvas)

            if (dropingNode != null) {
                drawRectAndContent(canvas, dropingNode!!, false)
            }

            drawRectAll(canvas, selectedNode!!, true)
            drawDelRect(canvas)
        }else{
            if(needSave){
                drawSaveRect(canvas)
            }
        }


    }

    private fun drawSaveRect(canvas: Canvas) {
        var saveRectTop = height - saveRectHeight
        paintBg.color = Color.parseColor("#4051B5");
        canvas.drawRect(0.0f,saveRectTop,
            width.toFloat(), height.toFloat(),paintBg)
        var text = "保存"

        val textWidth = paintText?.measureText(text)
        canvas.drawText(
            text,
            (width - textWidth!!) / 2,
            saveRectTop + (saveRectHeight + this.paintText?.textSize!!)/2 - 5,
            paintText!!
        )
    }

    private fun drawDelRect(canvas: Canvas) {
        var delRectTop = height - delRectHeight
        paintBg.color = Color.parseColor("#88ff0000");
        canvas.drawRect(0.0f,delRectTop,
            width.toFloat(), height.toFloat(),paintBg)
        var text = "拖动到这里删除"
        if(this.triggerDel){
            text = "松手即可删除"
        }

        val textWidth = paintText?.measureText(text)
        canvas.drawText(
            text,
            (width - textWidth!!) / 2,
            delRectTop + (delRectHeight + this.paintText?.textSize!!)/2 - 5,
            paintText!!
        )

    }

    private fun drawFloatTopTitle(canvas: Canvas) {
        var floatTitleMarginLeft = this.dp2px(24f).toFloat()
        var floatTitleMarginTop = this.dp2px(10f).toFloat()
        var floatTitleHeight = this.dp2px(36f).toFloat()
        var floatTitleWidth = this.width - floatTitleMarginLeft * 2
        var floatTitleBgLeft = floatTitleMarginLeft
        var floatTitleBgTop = floatTitleMarginTop
        paintBg.color = Color.parseColor("#99000000")
        canvas.drawRect(
            floatTitleBgLeft,
            floatTitleBgTop,
            floatTitleBgLeft + floatTitleWidth,
            floatTitleBgTop + floatTitleHeight,
            paintBg
        )
        var text = ""
        if(dropingNode == null) {
            text = "长按拖动可以改变  \"" + this.selectedNode?.name + "\"  在组织机构中的位置"
        }else{
            text = "松开，可以将  \""+this.selectedNode?.name+"\"  变更为  \""+this.dropingNode?.name+"\"  的下属"
        }
        val textWidth = paintText?.measureText(text)
        canvas.drawText(
            text,
            floatTitleBgLeft + (floatTitleWidth - textWidth!!) / 2,
            floatTitleBgTop + (floatTitleHeight + this.paintText?.textSize!!)/2 - 5,
            paintText!!
        )
    }

    private fun drawTopTitle(canvas: Canvas) {
        paintBg.color = Color.parseColor("#FAAD13");
        canvas.drawRect(0F, 0F, width.toFloat(), this.topTitleHeight, paintBg)
        canvas.drawText(
            "什么是组织机构？点击了解 >> ",
            this.dp2px(15f).toFloat(),
            (this.topTitleHeight + this.paintText?.textSize!!) / 2 - 5, paintText
        )
    }


    private fun drawRectAll(canvas: Canvas, rootNode: OrgTreeNode, isMovingRect: Boolean) {
        drawRect(canvas, rootNode, isMovingRect)
        rootNode.leftTreeNode?.let {
            drawLine2Aside(rootNode, it, canvas)
            drawRectAll(canvas, it, isMovingRect)
        }
        rootNode.rightTreeNode?.let {
            drawLine2Aside(rootNode, it, canvas)
            drawRectAll(canvas, it, isMovingRect)
        }
    }

    private fun drawLine2Aside(parentNode: OrgTreeNode, node: OrgTreeNode, canvas: Canvas) {
        var beginX = parentNode.left + nodeWidth / 2
        var beginY = parentNode.top + nodeHeight

        var endX = node.left
        var endY = node.top + nodeHeight / 2

        var pointX = beginX
        var pointY = endY

        canvas.drawLine(beginX, beginY, pointX, pointY, paintLine!!)
        canvas.drawLine(pointX, pointY, endX, endY, paintLine)
    }

    private fun calcAll() {
        //1、计算占用多少列，多少行
        calcColumnAndRowAll(nodeData)
        //计算wholeMarginLeft
        calcWholeMarginLeft()
        //2、计算每个节点的坐标
        calcXYAll(nodeData)
    }

    private fun calcWholeMarginLeft() {
        //计算所有列相加一共占用多少px
        var wholeColumnWidth = gridWidth * nodeData.columnNum
        if (wholeColumnWidth < width) {
            wholeMarginLeft = (width - wholeColumnWidth) / 2
        } else {
            wholeMarginLeft = 0.0f
        }
    }

    private fun calcColumnAndRowAll(rootNode: OrgTreeNode) {
        //先计算左边的树
        rootNode.leftTreeNode?.let {
            it.parentNode = rootNode
            calcColumnAndRowAll(it)
        }
        //再计算右边的树
        rootNode.rightTreeNode?.let {
            it.parentNode = rootNode
            calcColumnAndRowAll(it)
        }
        rootNode.columnNum = 0
        rootNode.rowNum = 0
        //最后计算中间的树
        calcColumn(rootNode, rootNode)
        calcRow(rootNode, rootNode, 0)
    }

    private fun calcXYAll(rootNode: OrgTreeNode) {
        //先计算中间
        calcXY(rootNode, rootNode)
        //再计算左边
        rootNode.leftTreeNode?.let { calcXYAll(it) }
        //再计算右边
        rootNode.rightTreeNode?.let { calcXYAll(it) }
    }


    private fun calcColumn(rootNode: OrgTreeNode, currentNode: OrgTreeNode) {
        if (currentNode.children == null || currentNode.children!!.size == 0) {
            //如果是叶子节点
            currentNode.column = rootNode.columnNum
            rootNode.columnNum++
        } else {
            currentNode.children?.forEach {
                it.parentNode = currentNode
                calcColumn(rootNode, it)
            }
        }
    }

    private fun calcRow(rootNode: OrgTreeNode, currentNode: OrgTreeNode, level: Int) {
        currentNode.row = level
        if (level >= rootNode.rowNum) {
            rootNode.rowNum = level + 1
        }
        currentNode.children?.forEach { calcRow(rootNode, it, level + 1) }
    }

    private fun drawRect(canvas: Canvas, node: OrgTreeNode, isMovingRect: Boolean) {
        drawRectAndContent(canvas, node, isMovingRect)

        node.children?.forEach {
            drawRect(canvas, it, isMovingRect)
            drawLine(canvas, node, it, isMovingRect)
        }
    }

    private fun drawRectAndContent(canvas: Canvas, node: OrgTreeNode, isMovingRect: Boolean) {
        rectF.left = node.left
        rectF.top = node.top
        rectF.right = node.right
        rectF.bottom = node.bottom

        if (!isMovingRect && node.isMoving) {
            paintRectFStroke.color = Color.parseColor("#5E77C7")
            canvas.drawRect(rectF, paintRectFStroke)
        } else {
            if (isMovingRect) {
                rectF.left += lastX - clickX
                rectF.top += lastY - clickY
                rectF.right = rectF.left + nodeWidth
                rectF.bottom = rectF.top + nodeHeight

                paintRectF.color = Color.WHITE
            } else {
                if (node != selectedNode) {
                    paintRectF.color = Color.WHITE
                } else {
                    paintRectF.color = Color.WHITE
                }
            }
            canvas.drawRect(rectF, paintRectF)

            paintRectFStroke.color = Color.parseColor("#44000000")
            canvas.drawRect(rectF, paintRectFStroke)
            canvas.drawText(
                node.name,
                rectF.left + nameMarginLeft,
                rectF.top + nameMarginTop,
                paintName!!
            )

            canvas.drawText(
                node.roleName,
                rectF.left + roleNameMarginLeft,
                rectF.top + roleNameMarginTop,
                paintRoleName!!
            )
            //在岗位下面画一条虚线
            var lineBeginX = rectF.left + (this.nodeWidth - this.roleBottomLineWidth) / 2
            var lineBeginY = rectF.top + this.roleNameMarginTop * 1.2
            var lineEndX = lineBeginX + this.roleBottomLineWidth
            var lineEndY = lineBeginY
            canvas.drawLine(lineBeginX, lineBeginY.toFloat(),lineEndX,
                lineEndY.toFloat(),paintDashLine )

            //在虚线下面画一个【+添加下属】按钮
            var btnText = "+添加下属"
            var btnTextWidth = paintAddBtn.measureText(btnText)
            var btnTextLeft = rectF.left + (this.nodeWidth - btnTextWidth) / 2
            var btnTextTop = lineBeginY + (rectF.bottom - lineBeginY + paintAddBtn.textSize) /2 - 5
            canvas.drawText(btnText,btnTextLeft, btnTextTop.toFloat(),paintAddBtn)
        }

    }

    /**
     * 在两个节点之间画一条线，这条线有可能是直线，有可能是折线
     */
    private fun drawLine(
        canvas: Canvas,
        parentNode: OrgTreeNode,
        node: OrgTreeNode,
        isMovingRect: Boolean
    ) {
        //计算起点的x,y
        var beginX = 0.0f
        var beginY = 0.0f
        var endX = 0.0f
        var endY = 0.0f
        beginX = parentNode.left + nodeWidth / 2
        beginY = parentNode.bottom

        //计算终点的x,y
        endX = node.left + nodeWidth / 2
        endY = node.top

        if (isMovingRect) {
            beginX += lastX - clickX
            beginY += lastY - clickY
            endX += lastX - clickX
            endY += lastY - clickY
        }
        //画三条线
        var pointY = beginY + (endY - beginY - (gridHeight - nodeHeight))
        //1、父节点  --- 父子节点垂直方向的中间
        canvas.drawLine(beginX, beginY, beginX, pointY, paintLine!!)
        //2、子节点 ---- 父子节点垂直方向的中间
        canvas.drawLine(endX, pointY, endX, endY, paintLine!!)
        //3、连接两条线
        canvas.drawLine(endX, pointY, beginX, pointY, paintLine!!)
    }

    private fun calcXY(rootNode: OrgTreeNode, currentNode: OrgTreeNode) {
        if (currentNode.children == null || currentNode.children!!.size == 0) {
            //如果是叶子节点
            currentNode.left = gridWidth * currentNode.column + ((gridWidth - nodeWidth) / 2)

            if (rootNode.parentNode != null) {
                if (rootNode == rootNode.parentNode!!.rightTreeNode) {
                    //如果是右边的树
                    currentNode.left += rootNode.parentNode!!.left + nodeWidth
                } else if (rootNode == rootNode.parentNode!!.leftTreeNode) {
                    //如果是左边的树
                    //当前节点的left + (columnNum - column) * gridWidth = parentNode.left
                    currentNode.left =
                        rootNode.parentNode!!.left - (rootNode.columnNum - currentNode.column) * gridWidth + (gridWidth - nodeWidth) / 2
                    //currentNode.left + nodeWidth = rootNode.parentNode.left
                }
            } else {
                //如果是总根节点，则加入wholeMarginLeft，还要考虑屏幕移动
                currentNode.left += wholeMarginLeft + lastScreenOffsetX + screenOffsetX
            }
        } else {
            //首先递归计算每个叶子节点的xy
            currentNode.children!!.forEach { calcXY(rootNode, it) }
            currentNode.left =
                (currentNode.children!!.get(currentNode.children!!.size - 1).left + currentNode.children!!.get(
                    0
                ).left) / 2
        }

        if (currentNode == rootNode) {
            //如果是根节点，则只根据自身column，row 计算top
            currentNode.top =
                (gridHeight + nodeMarginVertical) * currentNode.row + ((gridHeight - nodeHeight) / 2)
        } else {
            var asideRowNum = 0
            if (rootNode.leftTreeNode?.rowNum ?: 0 > asideRowNum) {
                asideRowNum = rootNode.leftTreeNode?.rowNum!!
            }
            if (rootNode.rightTreeNode?.rowNum ?: 0 > asideRowNum) {
                asideRowNum = rootNode.rightTreeNode?.rowNum!!
            }
            currentNode.top =
                (gridHeight + nodeMarginVertical) * (currentNode.row + asideRowNum) + ((gridHeight - nodeHeight) / 2)
        }
        if (rootNode.parentNode != null) {
            //左、右两侧树的高度相对于中间树向下移动一个单元格
            currentNode.top += rootNode.parentNode!!.top + gridHeight
        }

        if (rootNode == nodeData) {
            //如果是总的根节点，则整体向下移动martinTop,还要考虑屏幕移动距离
            currentNode.top += wholeMarginTop + lastScreenOffsetY + screenOffsetY
        }

        currentNode.right = currentNode.left + nodeWidth
        currentNode.bottom = currentNode.top + nodeHeight

    }

    private val runnable: Runnable = Runnable {
        kotlin.run {
            if (selectedNode != null) {
                //如果有被选中的节点，把状态设置为正在移动
                if (selectedNode != nodeData && selectedNode != selectedNode!!.parentNode?.leftTreeNode && selectedNode != selectedNode!!.parentNode?.rightTreeNode) {
                    selectedNode!!.isMoving = true
                    //递归把子节点都设置为正在移动
                    if (selectedNode?.isMoving == true) {
                        setMoving(selectedNode!!, true)
                    }
                    postInvalidate()
                }
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        lastX = event.x
        lastY = event.y
        when (event.action) {
            MotionEvent.ACTION_DOWN -> actionDown(event)
            261 -> pointDown(event)
            MotionEvent.ACTION_POINTER_DOWN -> pointDown(event)
            MotionEvent.ACTION_MOVE -> actionMove(event)
            MotionEvent.ACTION_UP -> actionUp(event)
            262 -> pointUp(event)
            MotionEvent.ACTION_POINTER_UP -> pointUp(event)
        }
        return true
    }

    private var oldDist = 0.0f
    private fun pointDown(event: MotionEvent) {
        canMovingScreen = false
        mMode++
        //Log.i("TAG","pointDown:mMode=" + mMode)
        oldDist = spacing(event)

    }

    private fun pointUp(event: MotionEvent) {
        if (mMode == 2) {
            prevZoomPercent *= zoomPercent
        }
        mMode--
    }

    /**
     * @param event 计算两点距离
     * @return
     */
    private fun spacing(event: MotionEvent): Float {
        val x = event.getX(0) - event.getX(1)
        val y = event.getY(0) - event.getY(1)
        return Math.sqrt((x * x + y * y).toDouble()).toFloat()
    }

    private fun actionMove(event: MotionEvent) {
        //Log.i("TAG","actionMove:mMode=" + mMode)
        dropingNode = null
        if (selectedNode?.isMoving == true) {
            //如果有标记可以移动的节点，开始移动
            //判断是否移动到了某一个可放置的节点上
            checkDropingNode(nodeData)
            //判断手指是否移动到了删除区域
            checkTriggerDel()

        } else {
            if (mMode >= 2) {
                //两个手指以上 两点间的距离
                val newDist = spacing(event)
                if (newDist > oldDist + 1) {
                    zoomPercent = newDist / oldDist
                    initPx()
                }
                if (newDist < oldDist - 1) {
                    zoomPercent = newDist / oldDist
                    initPx()
                }

            } else {
                //移动屏幕
                if (canMovingScreen) {
                    screenOffsetX = lastX - clickX
                    screenOffsetY = lastY - clickY
                }
            }
        }

        invalidate()
    }

    private fun checkTriggerDel() {
        var left = 0.0f;
        var top = height.toFloat() - this.delRectHeight
        var right = width.toFloat()
        var bottom = height.toFloat()
        this.triggerDel = lastX > left && lastX < right && lastY > top && lastY < bottom
    }

    private fun actionUp(event: MotionEvent) {
        removeCallbacks(runnable)
        mMode--
        canMovingScreen = false
        if (dropingNode != null) {
            //开始放置节点
            //1、从原来的父节点中移除当前selectedNode
            selectedNode?.parentNode?.children?.remove(selectedNode)
            //2、把selectNode添加到dropingNode子节点中
            selectedNode?.let {
                if (dropingNode!!.children == null) {
                    dropingNode!!.children = mutableListOf()
                }
                dropingNode?.children?.add(it)
            }

            selectedNode?.let { setMoving(it, false) }
            selectedNode = null
            dropingNode = null
            needSave = true
        }
        if(triggerDel){
            deleteSelectedNode()
        }

        if (selectedNode?.isMoving == true) {
            selectedNode?.let { setMoving(it, false) }
        } else {
            lastScreenOffsetX += screenOffsetX
            lastScreenOffsetY += screenOffsetY
            screenOffsetX = 0.0f
            screenOffsetY = 0.0f
        }

        invalidate()
    }

    //删除选中的节点
    private fun deleteSelectedNode() {
        if(this.selectedNode?.children == null || this.selectedNode?.children!!.size == 0) {
            selectedNode?.parentNode?.children?.remove(selectedNode)
            needSave = true
        }else{
            val builder = AlertDialog.Builder(context)
            builder.setTitle("无法删除")
            builder.setMessage("该员工包含下属，请先将他的下属调岗或离职，再行操作")
            builder.setPositiveButton("确定",null)
            builder.create().show()
        }
        this.triggerDel = false
    }


    private fun setMoving(node: OrgTreeNode, isMovingNode: Boolean) {
        node.isMoving = isMovingNode
        node.children?.forEach {
            setMoving(it, isMovingNode)
        }
        node.leftTreeNode?.let { setMoving(it, isMovingNode) }
        node.rightTreeNode?.let { setMoving(it, isMovingNode) }
    }

    private fun actionDown(event: MotionEvent) {
        mMode++
        canMovingScreen = true
        clickX = event.x
        clickY = event.y
        selectedNode = null
        canMovingScreen = true
        postDelayed(runnable, 400)
        checkSelectedNode(nodeData)
        invalidate()
    }

    private fun checkDropingNode(node: OrgTreeNode) {
        if (node.isMoving == false && node != selectedNode?.parentNode && lastX > node.left && lastX < node.right && lastY > node.top && lastY < node.bottom) {
            dropingNode = node
        } else {
            node.children?.forEach {
                checkDropingNode(it)
            }
            node.leftTreeNode?.let { checkDropingNode(it) }
            node.rightTreeNode?.let { checkDropingNode(it) }
        }
    }

    private fun checkSelectedNode(node: OrgTreeNode) {
        node.isMoving = false
        if (clickX > node.left && clickX < node.right && clickY > node.top && clickY < node.bottom) {
            selectedNode = node
        } else {
            node.children?.forEach {
                checkSelectedNode(it)
            }
            node.leftTreeNode?.let { checkSelectedNode(it) }
            node.rightTreeNode?.let { checkSelectedNode(it) }
        }
    }

    private fun getDensity(): Float {
        return mMetrics.density
    }

    private fun dp2px(dpValue: Float): Int {
        return (dpValue * getDensity() + 0.5f).toInt()
    }

    private fun sp2px(context: Context, spValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f).toInt()
    }
}